package flexconsole.controls {
	import flash.display.DisplayObject;
	import flash.events.MouseEvent;
	
	import mx.controls.ButtonPhase;
	import mx.controls.CheckBox;
	import mx.core.IFlexDisplayObject;
	import mx.core.mx_internal;
	import mx.skins.ProgrammaticSkin;
	
	use namespace mx_internal;
	
	/**
	 * An extended CheckBox component that supports Schrodinger state.
	 *
	 * <p>The Schrodinger state usually occurs in a tree structure when some of the parent
	 * node’s children are CHECKED state, UNCHECKED state and/or in Schrodinger state.</p>
	 *
	 * <p>The <code>schrodinger</code> property is independent of the <code>selected</code>,
	 * but it will affect the way the icons are displayed. When a <code>SchrodingerCheckBox</code>
	 * has the <code>schrodinger</code> property set to true, it displays a default square icon in
	 * the center of the check icon.</p>
	 *
	 * <p>You can set your own custom <code>schrodinger</code> icon by using the <code>schrodingerIcon</code> style.</p>
	 *
	 * @author ivanchoo
	 *
	 */
	public class SchrodingerCheckBox extends CheckBox {
		
		/**
		 * @private
		 */
		protected var _schrodinger:Boolean = false;
		
		/**
		 * @private
		 */
		protected var _schrodingerInteractive:Boolean = true;
		
		/**
		 * @private
		 */
		protected var _schrodingerIcon:IFlexDisplayObject;
		
		public function SchrodingerCheckBox() {
			super();
		}
		
		[Bindable]
		/**
		 * Defines if the checkbox is in a schrodinger state.
		 * @return
		 *
		 */
		public function get schrodinger():Boolean {
			return _schrodinger;
		}
		
		/**
		 * @private
		 */
		public function set schrodinger(bool:Boolean):void {
			_schrodinger = bool;
			invalidateDisplayList();
		}
		
		[Bindable]
		/**
		 * Defines if the <code>schrodinger</code> should be turned off whenever
		 * the user clicks on the checkbox.
		 * @return
		 *
		 */
		public function get schrodingerInteractive():Boolean {
			return _schrodingerInteractive;
		}
		
		/**
		 * @private
		 */
		public function set schrodingerInteractive(bool:Boolean):void {
			_schrodingerInteractive = bool;
		}
		
		/**
		 * @inheritDoc
		 */
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
			super.updateDisplayList(unscaledWidth, unscaledHeight);
			
			if (_schrodinger) {
				var ic:IFlexDisplayObject = schrodingerIcon;
				
				if (ic) {
					if (getChildAt(numChildren - 1) != ic) {
						removeChild(ic as DisplayObject);
						addChild(ic as DisplayObject);
					}
					ic.x = ((currentIcon.width - ic.width) / 2) + currentIcon.x;
					ic.y = ((currentIcon.height - ic.height) / 2) + currentIcon.y;
					ic.visible = true;
					ic.alpha = enabled ? 1 : 0.4;
				}
			} else {
				if (_schrodingerIcon) {
					_schrodingerIcon.visible = false;
				}
			}
		}
		
		/**
		 * @private
		 */
		override mx_internal function changeIcons():void {
			super.changeIcons();
			
			if (_schrodingerIcon && contains(_schrodingerIcon as DisplayObject)) {
				removeChild(_schrodingerIcon as DisplayObject);
				_schrodingerIcon = null;
			}
		}
		
		/**
		 * @private
		 */
		override mx_internal function getCurrentIconName():String {
			if (schrodinger) {
				//	When in schrodinger state, we always return the normal iconName
				//	regardless of the selected state
				if (!enabled) {
					return disabledIconName;
				} else if (phase == ButtonPhase.UP) {
					return upIconName;
				} else if (phase == ButtonPhase.OVER) {
					return overIconName;
				} else if (phase == ButtonPhase.DOWN) {
					return downIconName;
				}
			}
			return super.getCurrentIconName();
		}
		
		/**
		 * @inheritDoc
		 */
		override protected function clickHandler(event:MouseEvent):void {
			super.clickHandler(event);
			
			if (enabled && schrodingerInteractive) {
				schrodinger = false;
			}
		}
		
		/**
		 * @private
		 */
		protected function get schrodingerIcon():IFlexDisplayObject {
			if (!_schrodingerIcon) {
				//	lazy create
				var clz:Class = getStyle('schrodingerIcon');
				
				if (!clz) {
					//	not defined, we just draw a simple sprite
					var sk:ProgrammaticSkin = new ProgrammaticSkin();
					sk.width = 6;
					sk.height = 6;
					sk.graphics.beginFill(getStyle('color'), 1);
					sk.graphics.drawRect(0, 0, 6, 6);
					sk.graphics.endFill();
					_schrodingerIcon = sk;
				} else {
					_schrodingerIcon = new clz() as IFlexDisplayObject;
				}
				
				if (_schrodingerIcon) {
					//	hide first, will show when ready to update display
					addChild(_schrodingerIcon as DisplayObject);
					_schrodingerIcon.visible = false;
				}
			}
			return _schrodingerIcon;
		}
	}
}